/*
 * ClientConnectionHandler.java
 * 
 * @version 1.0, March 31, 2011
 * CS 2340 Team 10: Cyberdyne Systems
 */
package edu.gatech.oad.cyberdoc.net;

import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.json.JSONException;
import org.json.JSONObject;

/**
 * Transmits requests to the server and receives responses.
 * 
 * @author John Girata
 * @version 1.0, March 31, 2011
 */
public class ClientConnectionHandler implements Runnable {
	/**
	 * The host of the server.
	 */
	public static final String HOST = "localhost";

	/**
	 * This class's logger.
	 */
	private static final Logger LOG;

	/**
	 * The request to send to the server.
	 */
	private final JSONObject request;

	/**
	 * The classes listening for responses.
	 */
	private final ResponseListener[] callbacks;

	static {
		LOG = Logger.getLogger("edu.gatech.oad.cyberdoc.net."
				+ "ClientConnectionManager");
	}

	/**
	 * Creates a new handler to send the request to the server and notify the
	 * given listeners of the response.
	 * 
	 * @param request
	 *            The request for the server
	 * @param callbacks
	 *            The classes listening for responses
	 */
	public ClientConnectionHandler(JSONObject request,
			ResponseListener... callbacks) {
		this.request = request;
		this.callbacks = callbacks.clone();

	}

	/**
	 * Sends the request and listens for the response in a separate thread.
	 */
	@Override
	public void run() {
		LOG.info(toString() + " started");

		try {
			final Socket socket = new Socket(getHost(),
					ServerConnectionManager.getPort());
			final PrintStream output = new PrintStream(socket.getOutputStream());
			final Scanner input = new Scanner(socket.getInputStream());

			output.println(request);

			while (!input.hasNext())
				; // Wait for input

			final JSONObject response = new JSONObject(input.nextLine());

			for (ResponseListener listener : callbacks) {
				listener.responseReceived(response);
			}
		} catch (UnknownHostException e) {
			LOG.log(Level.SEVERE, "Unexpected exception", e);
		} catch (IOException e) {
			LOG.log(Level.SEVERE, "Unexpected exception", e);
		} catch (JSONException e) {
			LOG.log(Level.SEVERE, "Unexpected exception", e);
		}
	}

	/**
	 * Returns a string representation of this class.
	 * 
	 * @return A string representation of this class
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "ClientConnectionHandler [request=" + request + "]";
	}

	/**
	 * Returns the host that this ClientConnectionHandler will try to connect
	 * to.
	 * 
	 * @return The server's host
	 */
	public static String getHost() {
		return HOST;
	}
}
